package com.ghostbusters.fingertrack.application;

import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import com.ghostbusters.fingertrack.wii.IRPoint;
import com.ghostbusters.fingertrack.wii.WiiMain;
import com.ghostbusters.fingertrack.wii.WiiSubscriber;

public class Mouse implements WiiSubscriber {
	// public static void main(String[] args) throws AWTException,
	// InterruptedException {
	// Robot robot = new Robot();
	//
	// for (int i = 0; i < 500; i++) {
	// Thread.currentThread().sleep(10);
	// robot.mouseMove(i, i);
	// }
	//
	// robot.mouseMove(20, 20);
	//
	// }

	private Robot robot;
	private static final long clickThreshold = 100;
	
	private List<IRPoint> pastPoints;
	private static final int SHAKE_PAST = 5;
	private static final int CLOSENESS_THRESHOLD = 20;
	private static final double CLOSENESS_MODIFIER = 0.3;

	public Mouse() throws Exception {
		pastPoints = new ArrayList<IRPoint>();
		robot = new Robot();
		WiiMain.subscribe(this);
	}

	@Override
	public void newPoints(List<IRPoint> coords) {
		if (coords.size() > 1) {
			int topX = (int) (coords.get(0).getX() * 1366);
			int topY = (int) (coords.get(0).getY() * 768);

			int botX = (int) (coords.get(1).getX() * 1366);
			int botY = (int) (coords.get(1).getY() * 768);
			
			IRPoint destination = antiShaking(new IRPoint((topX + botX)/2, (topY + botY)/2));
			robot.mouseMove( (int)destination.getX(), (int)destination.getY());
			pastPoints.add(destination);
			
			double distance = Point2D.distance(topX, topY, botX, botY);
			if (clickThreshold > distance) {
				robot.mousePress(InputEvent.BUTTON1_MASK);
			} else {
				robot.mouseRelease(InputEvent.BUTTON1_MASK);
			}
		}
	}
	
	public IRPoint antiShaking(IRPoint irpoint) {
		
		if(pastPoints.size() <= SHAKE_PAST) {
			return irpoint;
		}
		
		double totalDistance = 0;
		
		for( int i = 0; i < SHAKE_PAST; i++) {
			IRPoint temp = pastPoints.get(pastPoints.size() - 1 - i);
			totalDistance += Point2D.distance(irpoint.getX(), irpoint.getY(), temp.getX(), temp.getY());
		}
		if( CLOSENESS_THRESHOLD > (totalDistance/SHAKE_PAST)) {
			return irpoint;
		}
		
		IRPoint prevPoint = pastPoints.get(pastPoints.size() - 1);
		
		double deltaX = irpoint.getX() - prevPoint.getX();
		double deltaY = irpoint.getY() - prevPoint.getY();
		
		return new IRPoint(prevPoint.getX() + deltaX * CLOSENESS_MODIFIER, prevPoint.getY() + deltaY * CLOSENESS_MODIFIER);
		
	}
}
